package com.wei.web.middleware.httpfilter.utils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.ObjectUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsUtils;

import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class CorsUtil {

    public static final String CORS_PATTERN_PREFIX = "Pattern_";
    public static final Pattern ZOOM_COMMON_URL_PATTERN = Pattern.compile("^((https|http|zoomus|zoommtg|zoomroom|zoomrooms)://)?([a-zA-Z0-9._-]+\\.)?((zoom|zoomdev)\\.us|(zoomgov|zipow)\\.com|zoom\\.com(\\.cn)?|meetzoom\\.net)(/.*)?$", Pattern.CASE_INSENSITIVE);

    public static String[] allowedOriginsFromPropertiesAndConstants(String allowedOriginsFromProperties) {
        String[] allowedOriginsArray = {};
        if (StringUtils.isNotEmpty(allowedOriginsFromProperties)) {
            allowedOriginsArray = allowedOriginsFromProperties.split(",");
        }

        // add meeting web domain
        allowedOriginsArray = Arrays.copyOf(allowedOriginsArray, allowedOriginsArray.length + 1);
        allowedOriginsArray[allowedOriginsArray.length - 1] = CORS_PATTERN_PREFIX + ZOOM_COMMON_URL_PATTERN.toString();

        return allowedOriginsArray;
    }

    /**
     * check origin whether in allowed origin property file.
     * @param allowedOriginsFromProperties
     * @param request
     * @return
     */
    public static boolean checkOrigin(String allowedOriginsFromProperties, HttpServletRequest request) {
        if (CorsUtils.isCorsRequest(request)) {
            String requestOrigin = new ServletServerHttpRequest(request).getHeaders().getOrigin();

            if (StringUtils.isNotBlank(requestOrigin)) {
                return checkHttpOriginIsInConfig(allowedOriginsFromProperties, requestOrigin);
            } else {
                log.debug("request origin not in allowed Origin property file: {}", requestOrigin);
                return false;
            }
        } else {
            return true;
        }
    }

    private static boolean checkHttpOriginIsInConfig(String allowedOriginsFromProperties, String requestOrigin) {
        // load allowed origins from properties and constants
        String[] allowedOrigins = allowedOriginsFromPropertiesAndConstants(allowedOriginsFromProperties);

        if (ObjectUtils.isEmpty(allowedOrigins)) {
            return false;
        }

        if (Arrays.stream(allowedOrigins).collect(Collectors.toList()).contains(CorsConfiguration.ALL)) {
            return true;
        }

        for (String allowedOrigin : allowedOrigins) {
            if (allowedOrigin.startsWith(CorsUtil.CORS_PATTERN_PREFIX)) {
                allowedOrigin = allowedOrigin.replace(CorsUtil.CORS_PATTERN_PREFIX, "");
                if (Pattern.matches(allowedOrigin, requestOrigin)) {
                    return true;
                }
            } else {
                if (requestOrigin.equalsIgnoreCase(allowedOrigin)) {
                    return true;
                }
            }
        }

        return false;
    }
}
